#include <iostream>
#include <string>

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_mixer.h>

/**
  * 声音测试
  */

using namespace std;

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces that will be used
SDL_Surface *background = NULL;
SDL_Surface *message = NULL;
SDL_Surface *screen = NULL;
//event
SDL_Event event;

//font
TTF_Font *font = NULL;
//the colore of the font
SDL_Color textColor = { 0, 0, 0 };

//The music that will be played
Mix_Music *music = NULL;

//The sound effects that will be used
Mix_Chunk *scratch = NULL;
Mix_Chunk *high = NULL;
Mix_Chunk *med = NULL;
Mix_Chunk *low = NULL;

SDL_Surface *load_image(string filename)
{
    SDL_Surface *loadedImage = NULL;

    SDL_Surface *optimizedImage = NULL;

    string current_dir = string(getenv("PROJECT_PATH"));
    if (current_dir.at(current_dir.length()-1) != '/')
            current_dir += '/';
    string sPath = current_dir + filename;

    //加载图片(PNG, JPG, BMP etc)
    loadedImage = IMG_Load(sPath.c_str());
    if (loadedImage != NULL) {
        //创建优化后的图像
        optimizedImage = SDL_DisplayFormat(loadedImage);

        //释放旧的图片
        SDL_FreeSurface(loadedImage);

        if (optimizedImage != NULL) {
            int colorkey = SDL_MapRGB(optimizedImage->format, 0, 0xff, 0xff);
             //Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
        }
    }

    return optimizedImage;
}

TTF_Font *load_font(string filename, int size)
{
    string current_dir = string(getenv("PROJECT_PATH"));
    if (current_dir.at(current_dir.length()-1) != '/')
            current_dir += '/';
    string sPath = current_dir + filename;

    TTF_Font *font = TTF_OpenFont(sPath.c_str(), size);

    return font;
}

Mix_Music *loadMusic(string filename)
{
    string current_dir = string(getenv("PROJECT_PATH"));
    if (current_dir.at(current_dir.length()-1) != '/')
            current_dir += '/';
    string sPath = current_dir + filename;

    Mix_Music *music = Mix_LoadMUS(sPath.c_str());

    return music;
}

Mix_Chunk *loadChunk(string filename)
{
    string current_dir = string(getenv("PROJECT_PATH"));
    if (current_dir.at(current_dir.length()-1) != '/')
            current_dir += '/';
    string sPath = current_dir + filename;

    Mix_Chunk *chunk = Mix_LoadWAV(sPath.c_str());

    return chunk;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
    //Holds offsets
    SDL_Rect offset;

    //Get offsets
    offset.x = x;
    offset.y = y;

    //Blit
    SDL_BlitSurface( source, clip, destination, &offset );
}

bool init()
{
    if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
        return false;

    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE);
    if (screen == NULL)
        return false;

    //Initialize SDL ttf
    if (TTF_Init() == -1)
        return false;

    //Initialize SDL_mixer
    if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 )
    {
        return false;
    }

    //Set the window caption
    SDL_WM_SetCaption( "声音测试", NULL );

    return true;
}

bool load_files()
{
    //load images
    background = load_image("background.png");

    if (background == NULL)
        return false;

    font = load_font("lazy.ttf", 30);
    if (font == NULL)
        return false;

    //Load music
    music = loadMusic("beat.wav");
    if (music == NULL)
        return false;

    //Load the sound effects
    scratch = loadChunk("scratch.wav");
    high = loadChunk("high.wav");
    med = loadChunk("medium.wav");
    low = loadChunk("low.wav");
    if (scratch == NULL || high == NULL
            || med == NULL || low == NULL)
        return false;

    return true;
}

void clean_up()
{
    //Free the surfaces
    SDL_FreeSurface(background);
    SDL_FreeSurface(message);

   //Close the font that was used
   TTF_CloseFont(font);

   //Quit SDL_ttf
   TTF_Quit();

   //Free the sound effects
   Mix_FreeChunk( scratch );
   Mix_FreeChunk( high );
   Mix_FreeChunk( med );
   Mix_FreeChunk( low );

   //Free the music
   Mix_FreeMusic( music );

   //Quit SDL_mixer
   Mix_CloseAudio();

   //Quit SDL
   SDL_Quit();
}

int main(int argc, char *argv[])
{
    //设置工程目录
    putenv("PROJECT_PATH=/home/fuyajun/myplayground/sdl/SDLTutorials/lesson11");

    bool quit = false;

    if (init() == false)
        return 1;

    if (load_files() == false)
        return 1;

    apply_surface(0, 0, background, screen);

    //Render the text
    message = TTF_RenderText_Solid( font, "Press 1, 2, 3, or 4 to play a sound effect", textColor );
    if (message == NULL)
        return 1;
    //Show the message on the screen
    apply_surface( ( SCREEN_WIDTH - message->w ) / 2, 100, message, screen );
    SDL_FreeSurface(message);

    //Render the text
    message = TTF_RenderText_Solid( font, "Press 9 to play or pause the music", textColor );
    if (message == NULL)
        return 1;
    //Show the message on the screen
    apply_surface( ( SCREEN_WIDTH - message->w ) / 2, 200, message, screen );
    SDL_FreeSurface(message);

    //Render the text
    message = TTF_RenderText_Solid( font, "Press 0 to stop the music", textColor );
    if (message == NULL)
        return 1;
    //Show the message on the screen
    apply_surface( ( SCREEN_WIDTH - message->w ) / 2, 300, message, screen );
    SDL_FreeSurface(message);

    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
        return 1;
    }

    while (quit == false) {

        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                quit = true;
            }

            if (event.type == SDL_KEYDOWN) {
                if (event.key.keysym.sym == SDLK_1) {
                    //Play the scratch effect
                    if( Mix_PlayChannel( -1, scratch, 0 ) == -1 )
                    {
                        return 1;
                    }
                } else if (event.key.keysym.sym == SDLK_2) {
                    //Play the high hit effect
                    if( Mix_PlayChannel( -1, high, 0 ) == -1 )
                    {
                        return 1;
                    }
                } else if (event.key.keysym.sym == SDLK_3) {
                    //Play the medium hit effect
                    if( Mix_PlayChannel( -1, med, 0 ) == -1 )
                    {
                        return 1;
                    }
                } else if (event.key.keysym.sym == SDLK_4) {
                    //Play the low hit effect
                   if( Mix_PlayChannel( -1, low, 0 ) == -1 )
                   {
                       return 1;
                   }
                } else if (event.key.keysym.sym == SDLK_9) {
                    //If there is no music playing
                    if( Mix_PlayingMusic() == 0 )
                    {
                        //Play the music
                        if( Mix_PlayMusic( music, -1 ) == -1 )
                        {
                            return 1;
                        }
                    }
                    //If music is being played
                    else
                    {
                        //If the music is paused
                        if( Mix_PausedMusic() == 1 )
                        {
                            //Resume the music
                            Mix_ResumeMusic();
                        }
                        //If the music is playing
                        else
                        {
                            //Pause the music
                            Mix_PauseMusic();
                        }
                    }
                } else if (event.key.keysym.sym == SDLK_0) {
                    //Stop the music
                    Mix_HaltMusic();
                }
            }
        }
    }

    clean_up();

    return 0;
}

